#include "WindowsService.h"
#include "Utils.h"

// ServiceManager 实现
ServiceManager::ServiceManager(const TCHAR *serviceName)
    : m_serviceName(serviceName) {}

BOOL ServiceManager::InstallService() {
  ServiceHandle schSCManager(OpenServiceManager());
  if (!schSCManager) {
    return FALSE;
  }

  TCHAR szPath[MAX_PATH];
  if (GetModuleFileName(NULL, szPath, MAX_PATH) == 0) {
    PrintError(_T("GetModuleFileName"), GetLastError());
    return FALSE;
  }

  ServiceHandle schService(CreateService(
      schSCManager, m_serviceName, m_serviceName,
      SERVICE_ALL_ACCESS | SERVICE_INTERACTIVE_PROCESS,
      SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
      szPath, NULL, NULL, NULL, NULL, NULL));

  if (!schService) {
    PrintError(_T("CreateService"), GetLastError());
    return FALSE;
  }
  return StartService(schService, 0, nullptr);
}

BOOL ServiceManager::UninstallService() {
  ServiceHandle schSCManager(OpenServiceManager());
  if (!schSCManager) {
    return FALSE;
  }

  ServiceHandle schService(
      OpenService(schSCManager, m_serviceName, SERVICE_ALL_ACCESS));
  if (!schService) {
    PrintError(_T("OpenService"), GetLastError());
    return FALSE;
  }

  SERVICE_STATUS serviceStatus;
  ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus);
  Sleep(1000);

  BOOL result = DeleteService(schService);
  if (!result) {
    PrintError(_T("DeleteService"), GetLastError());
  }
  return result;
}

SC_HANDLE ServiceManager::OpenServiceManager() {
  SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  if (!schSCManager) {
    PrintError(_T("OpenSCManager"), GetLastError());
  }
  return schSCManager;
}

// Service 实现

void WINAPI Service::ServiceMain(DWORD argc, LPTSTR *argv) {
  Service service(SERVICE_NAME);
  service.Run();
}

Service::Service(const TCHAR *serviceName)
    : m_serviceName(serviceName),
      m_hStopEvent(CreateEvent(NULL, TRUE, FALSE, NULL)) {
  m_status = {SERVICE_WIN32_OWN_PROCESS,
              SERVICE_STOPPED,
              SERVICE_ACCEPT_STOP,
              0,
              0,
              0,
              0};
}

void Service::Run() {
  LOG(_T("Service::Run entered"));
  m_statusHandle = RegisterServiceCtrlHandlerEx(m_serviceName, Handler, this);
  if (!m_statusHandle) {
    PrintError(_T("RegisterServiceCtrlHandlerEx"), GetLastError());
    return;
  }

  m_status.dwCheckPoint = 1;
  m_status.dwWaitHint = 3000;
  ReportStatus(SERVICE_START_PENDING);

  if (m_keyboardHandler.InstallHook()) {
    m_status.dwCheckPoint = 0;
    ReportStatus(SERVICE_RUNNING);

    while (m_status.dwCurrentState == SERVICE_RUNNING) {
      m_keyboardHandler.RunMessageLoop(m_hStopEvent);
    }
  } else {
    LOG(_T("Failed to install hook."));
  }

  m_status.dwCheckPoint = 1;
  m_status.dwWaitHint = 1000;
  ReportStatus(SERVICE_STOPPED);
}

DWORD WINAPI Service::Handler(DWORD control, DWORD eventType, LPVOID pEventData,
                              LPVOID pContext) {
  Service *instance = reinterpret_cast<Service *>(pContext);
  if (!instance)
    return ERROR_INVALID_HANDLE;

  switch (control) {
  case SERVICE_CONTROL_STOP:
    instance->m_status.dwCheckPoint = 1;
    instance->ReportStatus(SERVICE_STOP_PENDING);
    SetEvent(instance->m_hStopEvent); // 触发停止事件
    break;
  }
  return NO_ERROR;
}

void Service::ReportStatus(DWORD state) {
  m_status.dwCurrentState = state;
  SetServiceStatus(m_statusHandle, &m_status);
}
